/*
 * Copyright (c) 2022, Peter Abeles. All Rights Reserved.
 *
 * This file is part of Efficient Java Matrix Library (EJML).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ejml.dense.row.misc;

import org.ejml.data.ZMatrixRMaj;

/**
 * Algorithms for transposing row complex matrices
 *
 * @author Peter Abeles
 */
public class TransposeAlgs_ZDRM {
    /**
     * In-place transpose for a square matrix. On most architectures it is faster than the standard transpose
     * algorithm, but on most modern computers it's slower than block transpose.
     *
     * @param mat The matrix that is transposed in-place. Modified.
     */
    public static void square( ZMatrixRMaj mat ) {
        int index = 2;
        int rowStride = mat.getRowStride();
        int indexEnd = rowStride;
        for (int i = 0; i < mat.numRows;
             i++, index += (i + 1)*2, indexEnd += rowStride) {

            int indexOther = (i + 1)*rowStride + i*2;
            for (; index < indexEnd; index += 2, indexOther += rowStride) {
                double real = mat.data[index];
                double img = mat.data[index + 1];

                mat.data[index] = mat.data[indexOther];
                mat.data[index + 1] = mat.data[indexOther + 1];
                mat.data[indexOther] = real;
                mat.data[indexOther + 1] = img;
            }
        }
    }

    public static void squareConjugate( ZMatrixRMaj mat ) {
        int index = 2;
        int rowStride = mat.getRowStride();
        int indexEnd = rowStride;
        for (int i = 0; i < mat.numRows;
             i++, index += (i + 1)*2, indexEnd += rowStride) {

            mat.data[index - 1] = -mat.data[index - 1];

            int indexOther = (i + 1)*rowStride + i*2;
            for (; index < indexEnd; index += 2, indexOther += rowStride) {
                double real = mat.data[index];
                double img = mat.data[index + 1];

                mat.data[index] = mat.data[indexOther];
                mat.data[index + 1] = -mat.data[indexOther + 1];
                mat.data[indexOther] = real;
                mat.data[indexOther + 1] = -img;
            }
        }
    }

    /**
     * A straight forward transpose. Good for small non-square matrices.
     *
     * @param A Original matrix. Not modified.
     * @param A_tran Transposed matrix. Modified.
     */
    public static void standard( ZMatrixRMaj A, ZMatrixRMaj A_tran ) {
        int index = 0;
        int rowStrideTran = A_tran.getRowStride();
        int rowStride = A.getRowStride();
        for (int i = 0; i < A_tran.numRows; i++) {
            int index2 = i*2;

            int end = index + rowStrideTran;
            while (index < end) {
                A_tran.data[index++] = A.data[index2];
                A_tran.data[index++] = A.data[index2 + 1];
                index2 += rowStride;
            }
        }
    }

    /**
     * A straight forward conjugate transpose. Good for small non-square matrices.
     *
     * @param A Original matrix. Not modified.
     * @param A_tran Transposed matrix. Modified.
     */
    public static void standardConjugate( ZMatrixRMaj A, ZMatrixRMaj A_tran ) {
        int index = 0;
        int rowStrideTran = A_tran.getRowStride();
        int rowStride = A.getRowStride();
        for (int i = 0; i < A_tran.numRows; i++) {
            int index2 = i*2;

            int end = index + rowStrideTran;
            while (index < end) {
                A_tran.data[index++] = A.data[index2];
                A_tran.data[index++] = -A.data[index2 + 1];
                index2 += rowStride;
            }
        }
    }
}
